package com.baizw.cultivation.common.exception;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
import com.baizw.cultivation.common.response.ResultBean;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authz.AuthorizationException;
import org.apache.shiro.authz.UnauthorizedException;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.validation.ObjectError;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.multipart.MaxUploadSizeExceededException;
import org.springframework.web.servlet.NoHandlerFoundException;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 全局统一异常处理
 *
 * @author : baizw
 * Date: 2018/3/19
 * Time: 21:28
 */
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandle {

    /**
     * 处理自定义异常
     */
    @ExceptionHandler(GlobalException.class)
    public ResultBean handleRRException(GlobalException e) {
        log.error(e.getMessage(), e);
        return ResultBean.error(e.getMessage());
    }

    @ExceptionHandler(NoHandlerFoundException.class)
    public ResultBean handlerNoFoundException(Exception e) {
        log.error(e.getMessage(), e);
        return ResultBean.error(404, "路径不存在，请检查路径是否正确");
    }

    @ExceptionHandler(DuplicateKeyException.class)
    public ResultBean handleDuplicateKeyException(DuplicateKeyException e) {
        log.error(e.getMessage(), e);
        return ResultBean.error("数据库中已存在该记录");
    }

    @ExceptionHandler({UnauthorizedException.class, AuthorizationException.class})
    public ResultBean handleAuthorizationException(AuthorizationException e) {
        log.error(e.getMessage(), e);
        return ResultBean.authFailed("没有权限，请联系管理员授权");
    }

    @ExceptionHandler(Exception.class)
    public ResultBean handleException(Exception e) {
        log.error(e.getMessage(), e);
        return ResultBean.error("操作失败，" + e.getMessage());
    }

    @ExceptionHandler(ConstraintViolationException.class)
    public ResultBean handleException(ConstraintViolationException e) {
        log.error("参数校验异常", e);

        String message = e.getMessage();
        Set<ConstraintViolation<?>> constraintViolations = e.getConstraintViolations();
        if (CollUtil.isNotEmpty(constraintViolations)) {
            message = constraintViolations.parallelStream().map(ConstraintViolation::getMessage).collect(Collectors.joining(StrUtil.LF));
        }
        return ResultBean.error(message);
    }

    /**
     * 不支持的请求类型
     *
     * @param e
     * @return
     */
    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    public ResultBean HttpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException e) {
        String[] methods = e.getSupportedMethods();
        return ResultBean.error(405, StrUtil.format("不支持{}请求方法,支持以下{}", e.getMethod(), ArrayUtil.join(methods, "、")));
    }

    /**
     * 不支持的请求类型
     *
     * @param e
     * @return
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResultBean MethodArgumentNotValidException(MethodArgumentNotValidException e) {
        List<ObjectError> objectErrorList = e.getBindingResult().getAllErrors();
        String collect = objectErrorList.parallelStream().map(ObjectError::getDefaultMessage).collect(Collectors.joining(StrUtil.LF));
        return ResultBean.error(500, collect);
    }

    /**
     * spring默认上传大小100MB 超出大小捕获异常MaxUploadSizeExceededException
     */
    @ExceptionHandler(MaxUploadSizeExceededException.class)
    public ResultBean handleMaxUploadSizeExceededException(MaxUploadSizeExceededException e) {
        log.error(e.getMessage(), e);
        return ResultBean.error("文件大小超出10MB限制, 请压缩或降低文件质量! ");
    }

    @ExceptionHandler(DataIntegrityViolationException.class)
    public ResultBean handleDataIntegrityViolationException(DataIntegrityViolationException e) {
        log.error(e.getMessage(), e);
        return ResultBean.error("字段太长,超出数据库字段的长度");
    }
}
